﻿﻿// hooks/useRequest/config.ts
import { RequestOptions } from "./types";

// 全局默认配置
let globalConfig: RequestOptions = {
    // 默认请求方法
    method: "POST",
    // 默认超时时间 (30秒)
    timeout: 30000,
    // 默认显示错误
    showError: true,
    // 默认携带token
    withToken: true,
    // 默认不缓存
    cacheTime: 0,
    // 默认不使用防抖
    debounce: false,
    debounceTime: 300,
    // 默认不使用节流
    throttle: false,
    throttleTime: 300,
    // 默认不轮询
    pollingInterval: 0,
    pollingMaxCount: 0,
    // 默认自动执行
    manual: false,
    // 默认优先级
    priority: 0
};

// 全局基础URL
let baseURL = "";

// 拦截器类型
export interface Interceptor {
    request?: (config: RequestOptions) => RequestOptions | Promise<RequestOptions>;
    response?: <T = any>(response: T, config: RequestOptions) => T | Promise<T>;
    error?: (error: Error, config: RequestOptions) => Error | void | Promise<Error | void>;
}

// 拦截器列表
const interceptors: Interceptor[] = [];

/**
 * 设置全局配置
 * @param config 全局配置
 */
export const setConfig = (config: Partial<RequestOptions>): void => {
    globalConfig = { ...globalConfig, ...config };
};

/**
 * 获取全局配置
 * @returns 全局配置
 */
export const getConfig = (): RequestOptions => {
    return { ...globalConfig };
};

/**
 * 设置基础URL
 * @param url 基础URL
 */
export const setBaseURL = (url: string): void => {
    baseURL = url.endsWith("/") ? url.slice(0, -1) : url;
};

/**
 * 获取基础URL
 * @returns 基础URL
 */
export const getBaseURL = (): string => {
    return baseURL;
};

/**
 * 添加拦截器
 * @param interceptor 拦截器对象
 * @returns 拦截器ID，用于移除
 */
export const addInterceptor = (interceptor: Interceptor): number => {
    interceptors.push(interceptor);
    return interceptors.length - 1;
};

/**
 * 移除拦截器
 * @param index 拦截器ID
 */
export const removeInterceptor = (index: number): void => {
    if (index >= 0 && index < interceptors.length) {
        interceptors.splice(index, 1);
    }
};

/**
 * 清空所有拦截器
 */
export const clearInterceptors = (): void => {
    interceptors.length = 0;
};

/**
 * 应用请求拦截器
 * @param config 请求配置
 * @returns 处理后的请求配置
 */
export const applyRequestInterceptors = async (config: RequestOptions): Promise<RequestOptions> => {
    let currentConfig = config;

    for (const interceptor of interceptors) {
        if (interceptor.request) {
            const result = interceptor.request(currentConfig);
            if (result instanceof Promise) {
                currentConfig = await result;
            } else {
                currentConfig = result;
            }
        }
    }

    return currentConfig;
};

/**
 * 应用响应拦截器
 * @param response 响应数据
 * @param config 请求配置
 * @returns 处理后的响应数据
 */
export const applyResponseInterceptors = async <T>(response: T, config: RequestOptions): Promise<T> => {
    let currentResponse = response;

    for (const interceptor of interceptors) {
        if (interceptor.response) {
            const result = interceptor.response<T>(currentResponse, config);
            if (result instanceof Promise) {
                currentResponse = await result;
            } else {
                currentResponse = result;
            }
        }
    }

    return currentResponse;
};

/**
 * 应用错误拦截器
 * @param error 错误对象
 * @param config 请求配置
 * @returns 处理后的错误对象，如果返回undefined则表示错误已被处理
 */
export const applyErrorInterceptors = async (error: Error, config: RequestOptions): Promise<Error | undefined> => {
    let currentError: Error | undefined = error;

    for (const interceptor of interceptors) {
        if (interceptor.error && currentError) {
            const result = interceptor.error(currentError, config);
            if (result instanceof Promise) {
                const resolvedResult = await result;
                // `void` at runtime is `undefined`, which is falsy. An Error object is truthy.
                currentError = resolvedResult || undefined;
            } else {
                // `void` at runtime is `undefined`, which is falsy. An Error object is truthy.
                currentError = result || undefined;
            }
        }
    }

    return currentError;
};

/**
 * 解析URL，添加baseURL
 * @param url 原始URL
 * @returns 解析后的URL
 */
export const resolveURL = (url: string): string => {
    // 如果是完整URL或者以/开头，则直接返回
    if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//")) {
        return url;
    }

    // 如果baseURL为空，则直接返回原始URL
    if (!baseURL) {
        return url;
    }

    // 拼接baseURL和URL
    return `${baseURL}${url.startsWith("/") ? url : `/${url}`}`;
};

/**
 * 创建一个请求拦截器
 * @param handler 请求处理函数
 * @returns 拦截器对象
 */
export const createRequestInterceptor = (
    handler: (config: RequestOptions) => RequestOptions | Promise<RequestOptions>
): Interceptor => {
    return {
        request: handler
    };
};

/**
 * 创建一个响应拦截器
 * @param handler 响应处理函数
 * @returns 拦截器对象
 */
export const createResponseInterceptor = <T = any>(
    handler: (response: T, config: RequestOptions) => T | Promise<T>
): Interceptor => {
    return {
        response: <R>(res: R, config: RequestOptions) => {
            // 这里需要做一个类型转换，因为我们不能保证T和R是相同的类型
            return handler(res as unknown as T, config) as unknown as R;
        }
    };
};

/**
 * 创建一个错误拦截器
 * @param handler 错误处理函数
 * @returns 拦截器对象
 */
export const createErrorInterceptor = (
    handler: (error: Error, config: RequestOptions) => Error | void | Promise<Error | void>
): Interceptor => {
    return {
        error: handler
    };
};
